#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

using connection_t = std::shared_ptr<Connection>;
using namespace EpollModule;

class EpollServer
{
    const static int event_num = 64;
    bool IsConnectionExists(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }
public:
    EpollServer():_isrunning(false), _epoller(std::make_unique<Epoller>())
    {
        _epoller->Init();
    }
    void InsertConnection(connection_t conn)
    {
        //_connections[sockfd]->InitCB(recver,sender,excepter);
        auto iter = _connections.find(conn->Sockfd());
        if(iter == _connections.end())
        {
            //注册进哈希表进行管理
            _connections[conn->Sockfd()] = conn;
            //写进内核的epoll中
            _epoller->Ctrl(conn->Sockfd(), conn->GetEvents());
            //设置关联关系，让connection回执当前对象
            conn->SerOwner(this);
            LOG(LogLevel::DEBUG)<<"add Connection successs";
        }
    }

    //基于事件驱动的事件派发器
    void Dispatch(int n)
    {
        for(int i = 0; i < n; i++)
        {
            //开始进行事件派发
            int sockfd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            if((revents & EPOLLERR) || (revents & EPOLLHUP))
                revents = (EPOLLIN | EPOLLOUT); //异常事件，转换为读写事件
            if((revents & EPOLLIN) && IsConnectionExists(sockfd))
            {
                _connections[sockfd]->_Recver();
            }
            if((revents & EPOLLOUT) && IsConnectionExists(sockfd))
            {
                _connections[sockfd]->_Sender();
            }
        }
    }
    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revs, event_num, timeout); //返回就绪的fd数量
        Dispatch(n);
    }
    
    void Loop()
    {
        _isrunning = true;
        int timeout = -1;
        while(_isrunning)
        {
            LoopOnce(timeout);
            //超时管理
        }   
        _isrunning = false;
    }
    ~EpollServer()
    {}
private:
    std::unique_ptr<Epoller> _epoller;
    std::unordered_map<int, connection_t> _connections;//内部所有连接
    bool _isrunning;

    struct epoll_event _revs[event_num];
};
